﻿using System;
using System.Reflection;
using System.Threading;
using System.Windows.Markup;

namespace RSkor.Common.WinForms
{
    public class ReferenceExtension : MarkupExtension
    {
        public string Name { get; set; }

        public bool IsResource { get; set; }

        protected object TargetObject { get; set; }

        protected PropertyInfo TargetProperty { get; set; }

        public ReferenceExtension(string name)
        {
            this.Name = name;
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            object result = null;
            IRootObject root = MarkupHelper.LoadingObjects[Thread.CurrentThread].Peek();

            if (!string.IsNullOrEmpty(Name))
            {
                result = root.FindName(Name);
            }
            else
            {
                root.Resources.TryGetValue(Name, out result);
            }
            if (result == null)
                // Register unresolved reference
            {
                IProvideValueTarget service = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
                if (service != null)
                {
                    PropertyInfo pi = service.TargetProperty as PropertyInfo;
                    if (pi != null && service.TargetObject != null)
                    {
                        this.TargetObject = service.TargetObject;
                        this.TargetProperty = pi;
                        root.UnresolvedReferences.Add(this);
                    }
                }
            }

            return result;
        }

        internal virtual bool ResolveReference(IRootObject root)
        {
            object refer = null;
            if (!string.IsNullOrEmpty(Name))
            {
                refer = root.FindName(Name);
            }
            else
            {
                root.Resources.TryGetValue(Name, out refer);
            }

            if (refer != null)
            {
                TargetProperty.SetValue(TargetObject, refer, null);
                return true;
            }

            return false;
        }

    }
}
